package com.example.activiti.controller;

import com.example.activiti.component.MailComponent;
import com.example.activiti.component.ProcessUtils;
import com.example.activiti.po.ActivitiPo;
import com.example.activiti.service.ActivitiService;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.security.auth.x500.X500Principal;

import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.javassist.expr.NewArray;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/demo")
public class DemoController {
    @Autowired
    //Activiti 中每一个不同版本的业务流程的定义都需要使用一些定义文件，部署文件和支持数据 ( 例如 BPMN2.0 XML 文件，表单定义文件，流程定义图像文件等 )，
//    这些文件都存储在 Activiti 内建的 Repository 中。Repository Service 提供了对 repository 的存取服务。
    private RepositoryService repositoryService;
    @Autowired
    //在 Activiti 中，每当一个流程定义被启动一次之后，都会生成一个相应的流程对象实例。
//    Runtime Service 提供了启动流程、查询流程实例、设置获取流程实例变量等功能。此外它还提供了对流程部署，流程定义和流程实例的存取服务。
    private RuntimeService runtimeService;
    @Autowired
    //在 Activiti 中业务流程定义中的每一个执行节点被称为一个 Task，对流程中的数据存取，状态变更等操作均需要在 Task 中完成。
//    Task Service 提供了对用户 Task 和 Form 相关的操作。它提供了运行时任务查询、领取、完成、删除以及变量设置等功能
    private TaskService taskService;
    
    
//    @Autowired
////    Activiti 中内置了用户以及组管理的功能，必须使用这些用户和组的信息才能获取到相应的 Task。
////    Identity Service 提供了对 Activiti 系统中的用户和组的管理功能。
//    IdentityService identityService;
//
//    @Autowired
//    //通过使用 Form Service 可以存取启动和完成任务所需的表单数据并且根据需要来渲染表单
//    FormService fromService;
//
    @Autowired
//    Management Service 提供了对 Activiti 流程引擎的管理和维护功能
//    ，这些功能不在工作流驱动的应用程序中使用，主要用于 Activiti 系统的日常维护。
    ManagementService managementService;
    
    @Autowired
//    History Service 用于获取正在运行或已经完成的流程实例的信息，与 Runtime Service 
//    中获取的流程信息不同，历史信息包含已经持久化存储的永久信息，并已经被针对查询优化。
    HistoryService historyService;


    @Autowired
    MailComponent mailComponent;
    
    @Autowired
    ActivitiService activitiService;
    
    @GetMapping("sendMail")
    public Object  sendMail(){
        mailComponent.sendMail("fang101056@outlook.com");

        return "发送成功";
    }

    @GetMapping("sendHtmlMail")
    public Object  sendHtmlMail(){
        mailComponent.sendHtmlMail();

        return "发送成功";
    }

    @RequestMapping("/firstDemo")
    public void firstDemo() {
 
        //根据bpmn文件部署流程
        Deployment deployment = repositoryService.createDeployment().addClasspathResource("processes/demo2.bpmn").deploy();
        //获取流程定义
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult();
        //启动流程定义，返回流程实例
        ProcessInstance pi = runtimeService.startProcessInstanceById(processDefinition.getId());
        String processId = pi.getId();
        System.out.println("流程创建成功，当前流程实例ID："+processId);
 
        Task task=taskService.createTaskQuery().processInstanceId(processId).singleResult();
        System.out.println("第一次执行前，任务名称："+task.getName());
        taskService.complete(task.getId());
 
        task = taskService.createTaskQuery().processInstanceId(processId).singleResult();
        System.out.println("第二次执行前，任务名称："+task.getName());
        taskService.complete(task.getId());
 
        task = taskService.createTaskQuery().processInstanceId(processId).singleResult();
        System.out.println("task为null，任务执行完毕："+task);
    }
    
    @GetMapping("start")
    public Object startProcess(String owner) {
    	
    	ActivitiPo po = new ActivitiPo();
    	po.setOwner(owner);
    	
    	return activitiService.startProcess(po);
    	
    }
    
    @GetMapping("getTasks")
    public Object getTasks(ActivitiPo po) {
    	  List<String> taskIds = new ArrayList<>();
//          String userId = "H201H7W";
    	  
    	  TaskQuery query = taskService.createTaskQuery();
    	  
          if (StringUtils.isNoneBlank(po.getPid())){
        	  query.processInstanceId(po.getPid());
             
          }
          if (StringUtils.isNoneBlank(po.getOwner())) {
			query.taskAssignee(po.getOwner());
		}
          query.list().forEach(x->{
        	  taskIds.add(x.getId());
          });
          
          return taskIds;
    }
    
    @PostMapping("approve")
    public Object approve(ActivitiPo entity){

    	String userId = "H201H7W";


        if (StringUtils.isNoneBlank(entity.getMsg())){
            taskService.addComment(entity.getTaskId(),entity.getPid(),entity.getMsg());
        }
        
        //开始设置流程参数
        Map<String,Object> variables = new HashMap<>();
       
        
        if (StringUtils.isNoneBlank(entity.getProcessor())) {
			variables.put("processor", entity.getProcessor());
		}
        variables.put("directEnd", 0);
        taskService.setVariables(entity.getTaskId(), variables);

        taskService.complete(entity.getTaskId());

        return "提交成功";

    }
    
    @Autowired
    ProcessUtils processUtils;
    
    @PostMapping("goBack")
    public Object goBack(ActivitiPo po) {
    	
    	processUtils.goBack(po.getTaskId(), "回退111", po.getAssignee());
    	return "回退成功";
    	
    }
    
    
}